//! 亮点：
//! * 非 'static 的方式使用 `embassy_sync::zerocopy_channel::Channel`
//! * 非 embassy-executor 执行器

#![feature(future_join)]

use embassy_sync::{
    blocking_mutex::raw::NoopRawMutex,
    zerocopy_channel::{self as zc, Channel},
};

#[pollster::main]
async fn main() {
    let mut buf = [const { Side::Producer(0) }; BUF_LEN];
    let mut channel = Channel::<NoopRawMutex, _>::new(&mut buf);
    let (tx, rx) = channel.split();

    core::future::join!(consumer(rx), producer(tx)).await;
}

type Sender<'a> = zc::Sender<'a, NoopRawMutex, Side>;
type Receiver<'a> = zc::Receiver<'a, NoopRawMutex, Side>;

#[derive(Debug)]
enum Side {
    Producer(i32),
    Consumer(i32),
}

const BUF_LEN: usize = 3;
const STOP: usize = 10;

async fn producer(mut sender: Sender<'_>) {
    for i in 0..STOP {
        let val = sender.send().await;
        match val {
            Side::Producer(0) => (), // ignore init value
            Side::Producer(_) => eprintln!("Not good: a producer got {val:?}"),
            &mut Side::Consumer(n) => {
                *val = Side::Producer(n + 1);
                println!("[producer] i={i} got={:?}", Side::Consumer(n));
            }
        }
        sender.send_done();
    }
}

async fn consumer(mut receiver: Receiver<'_>) {
    for j in 0..STOP {
        let val = receiver.receive().await;
        match val {
            &mut Side::Producer(n) => {
                *val = Side::Consumer(n + 1);
                println!("[consumer] j={j} got={:?}", Side::Producer(n));
            }
            Side::Consumer(_) => eprintln!("Not good: a consumer got {val:?}"),
        }
        receiver.receive_done();
    }
}
